using System;
using System.Collections.Generic;

namespace AvaloniaDrawingPad.Models.Commands
{
    /// <summary>
    /// 命令管理器，负责管理撤销和重做历史
    /// </summary>
    public class CommandManager
    {
        // 单例模式
        private static CommandManager? _instance;
        public static CommandManager Instance => _instance ??= new CommandManager();
        
        // 撤销栈和重做栈
        private readonly Stack<ICommand> _undoStack = new Stack<ICommand>();
        private readonly Stack<ICommand> _redoStack = new Stack<ICommand>();
        
        // 最大历史记录数
        private const int MAX_HISTORY = 50;
        
        // 状态变更事件
        public event EventHandler? StateChanged;
        
        // 私有构造函数（单例模式）
        private CommandManager() { }
        
        /// <summary>
        /// 执行命令
        /// </summary>
        public void ExecuteCommand(ICommand command)
        {
            // 执行命令
            command.Execute();
            
            // 添加到撤销栈
            _undoStack.Push(command);
            
            // 清空重做栈
            _redoStack.Clear();
            
            // 如果撤销栈超过最大历史记录数，移除最早的命令
            if (_undoStack.Count > MAX_HISTORY)
            {
                // 创建临时列表
                var tempList = new List<ICommand>(_undoStack);
                
                // 移除最早的命令
                tempList.RemoveAt(tempList.Count - 1);
                
                // 重新构建撤销栈
                _undoStack.Clear();
                for (int i = tempList.Count - 1; i >= 0; i--)
                {
                    _undoStack.Push(tempList[i]);
                }
            }
            
            // 触发状态变更事件
            OnStateChanged();
        }
        
        /// <summary>
        /// 撤销最近的命令
        /// </summary>
        public bool Undo()
        {
            if (_undoStack.Count == 0)
                return false;
                
            // 从撤销栈中弹出最近的命令
            var command = _undoStack.Pop();
            
            // 撤销命令
            command.Undo();
            
            // 添加到重做栈
            _redoStack.Push(command);
            
            // 触发状态变更事件
            OnStateChanged();
            
            return true;
        }
        
        /// <summary>
        /// 重做最近撤销的命令
        /// </summary>
        public bool Redo()
        {
            if (_redoStack.Count == 0)
                return false;
                
            // 从重做栈中弹出最近的命令
            var command = _redoStack.Pop();
            
            // 执行命令
            command.Execute();
            
            // 添加到撤销栈
            _undoStack.Push(command);
            
            // 触发状态变更事件
            OnStateChanged();
            
            return true;
        }
        
        /// <summary>
        /// 清空历史记录
        /// </summary>
        public void Clear()
        {
            _undoStack.Clear();
            _redoStack.Clear();
            
            // 触发状态变更事件
            OnStateChanged();
        }
        
        /// <summary>
        /// 获取是否可以撤销
        /// </summary>
        public bool CanUndo => _undoStack.Count > 0;
        
        /// <summary>
        /// 获取是否可以重做
        /// </summary>
        public bool CanRedo => _redoStack.Count > 0;
        
        /// <summary>
        /// 获取最近的撤销命令描述
        /// </summary>
        public string? UndoDescription => CanUndo ? _undoStack.Peek().Description : null;
        
        /// <summary>
        /// 获取最近的重做命令描述
        /// </summary>
        public string? RedoDescription => CanRedo ? _redoStack.Peek().Description : null;
        
        /// <summary>
        /// 触发状态变更事件
        /// </summary>
        private void OnStateChanged()
        {
            StateChanged?.Invoke(this, EventArgs.Empty);
        }
    }
} 